package com.test.A13;

import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;


/****
 * 模拟cglib代理类   跟jdk代理思路一样    需要使用的是MethodInterceptor接口 
 * @author Administrator
 *
 */
public class Proxy extends Target {

    private MethodInterceptor methodInterceptor;

    public void setMethodInterceptor(MethodInterceptor methodInterceptor) {
        this.methodInterceptor = methodInterceptor;
    }

    
    /*****
     * 使用静态方法来得到方法名
     */
    static Method save0;
    static Method save1;
    static Method save2;
    //MethodProxy来实现代理方法    步骤一  定义MethodProxy方法对象
    static MethodProxy save0Proxy;
    static MethodProxy save1Proxy;
    static MethodProxy save2Proxy;
    static {
        try {
            save0 = Target.class.getMethod("save");
            save1 = Target.class.getMethod("save", int.class);
            save2 = Target.class.getMethod("save", long.class);
            //步骤二 得到MethodProxy方法对象
            save0Proxy = MethodProxy.create(Target.class, Proxy.class, "()V", "save", "saveSuper");
            //参数的含义  1目标对象 2代理对象  3大括号是无参V说明返回值是void   ()V 偏底层写法     4save是增强的方法名   5saveSuper原始的方法名
            save1Proxy = MethodProxy.create(Target.class, Proxy.class, "(I)V", "save", "saveSuper");
            save2Proxy = MethodProxy.create(Target.class, Proxy.class, "(J)V", "save", "saveSuper");
        } catch (NoSuchMethodException e) {
            throw new NoSuchMethodError(e.getMessage());
        }
    }
    // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 带原始功能的方法  //步骤三  创建原始的方法
    public void saveSuper() {
        super.save();
    }
    public void saveSuper(int i) {
        super.save(i);
    }
    public void saveSuper(long j) {
        super.save(j);
    }
    
    // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 带增强功能的方法
    @Override
    public void save() {
        try {
        	//步骤四 传入参数
            methodInterceptor.intercept(this, save0, new Object[0], save0Proxy);
            //一 代理对象  二 当前需要增强的方法  三 方法参数   四 代理方法
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public void save(int i) {
        try {
            methodInterceptor.intercept(this, save1, new Object[]{i}, save1Proxy);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public void save(long j) {
        try {
            methodInterceptor.intercept(this, save2, new Object[]{j}, save2Proxy);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }
}
